/*
 * Cluster class
 * the color param is color when we draw in 2dGraphics
 * 
 * */
package kmeansclustering;

import java.util.ArrayList;
import java.util.Iterator;
import kmeansclustering.KMeans;

public class Cluster {

    public float sumError;
    public float[] centroid;
    public ArrayList<Integer> listSamples;
    public int color;
    KMeans parrent;
    
    boolean checkReset;

    public Cluster() {
        this.checkReset = false;
        this.sumError = 0;
        this.centroid = new float[24];
        this.color = 0;
        listSamples = new ArrayList<>();
    }

    public Cluster(KMeans parrent) {
        if (parrent.equals(null)) {
            return;
        }
        this.checkReset = false;
        this.sumError = 0;
        this.centroid = new float[24];
        this.color = 0;
        this.parrent = parrent;
        listSamples = new ArrayList<>();
    }

    public void setParrent(KMeans parrent) {
        if (!parrent.equals(null)) {
            this.parrent = parrent;
        }
    }

    public void setCentroid(int id) {
        this.centroid = parrent.data[id];
    }

    public void setCentroid(float[] point) {
        this.centroid = point;
    }

    public float getDistance(float[] point) {
        float distance = eclipseDistance(centroid, point, 24);
        return distance;
    }

    public float getDistance(int id) {
        float distance = eclipseDistance(centroid, parrent.data[id], 24);
        return distance;
    }

    public float getSquareDistance(float[] point) {
        float distance = 0;
        distance = squareEclipseDistance(centroid, point, 24);
        return distance;
    }

    public float getSquareDistance(int id) {
        float distance = 0;
        distance = squareEclipseDistance(centroid, parrent.data[id], 24);
        return distance;
    }

    public float squareEclipseDistance(float[] A, float[] B, int dimension) {
        float sum = 0;
        for (int i = 0; i < dimension; i++) {
            sum += Math.pow((double) (A[i] - B[i]), 2);
        }
        return sum;
    }

    public float eclipseDistance(float[] A, float[] B, int dimension) {
        float sum = 0;
        for (int i = 0; i < dimension; i++) {
            sum += Math.pow((double) (A[i] - B[i]), 2);
        }
        return (float) Math.sqrt(sum);
    }

    public void addSample(int id, float squareDistance) {
        boolean checkExist = false;
//        for (int i = 0; i < listSamples.size(); i++) {
//            if (id == listSamples.get(i)) {
//                checkExist = true;
//                break;
//            }
//        }
        if (!checkExist) {
            listSamples.add(id);
            if(checkReset){
                sumError = 0;
                listSamples.clear();
                checkReset = false;
            }
            sumError += squareDistance;
        }
    }
    // calculate then reset centroid of cluster

    public void resetCentroid() {
        float[] trongTam = new float[24];
        int sizeListSample = listSamples.size();
        for (int i = 0; i < sizeListSample; i++) {
            for (int j = 0; j < 24; j++) {
                trongTam[j] += this.parrent.data[listSamples.get(i)][j];
            }
        }
        for (int i = 0; i < 24; i++) {
            trongTam[i] /= sizeListSample;
        }

        centroid = trongTam;
        this.checkReset = true;
    }

    public void reset() {
        resetCentroid();
        int sizeOfListSample = listSamples.size();
        float sumOfError = 0;
        for (int i = 0; i < sizeOfListSample; i++) {
            // listSamples.get(i) is index of i'th sample in data[][]
            sumOfError += getSquareDistance(this.parrent.data[listSamples.get(i)]);
        }
    }
}
